from flask import Flask, render_template, request, url_for, request, Blueprint, current_app, session
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin, LoginManager, login_required, login_user, logout_user
from flask_restful import reqparse, abort, Api, Resource
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_httpauth import HTTPBasicAuth
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
import os

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__, static_url_path='')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + \
    os.path.join(basedir, 'data.db')
app.config['SECRET_KEY'] = 'liuweichang'

api_bp = Blueprint('api', __name__)
api = Api(api_bp)
db = SQLAlchemy(app)
login_manager = LoginManager(app)
migrate = Migrate(app, db)
auth = HTTPBasicAuth()

login_manager.login_view = 'login'

# 数据库部分


class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    @property
    def password(self):
        raise AttributeError('没有权限查看密码！')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def generate_auth_token(self, expiration):
        s = Serializer(current_app.config['SECRET_KEY'],
                       expires_in=expiration)
        return s.dumps({'id': self.id}).decode('utf-8')

    @staticmethod
    def verify_auth_token(token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except:
            return None
        return User.query.get(data['id'])

    def __repr__(self):
        return '<User %r>' % self.username


class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    introduction = db.Column(db.String(64))
    users = db.relationship('User', backref='role')

    def __repr__(self):
        return '<Role %r>' % self.name


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


@auth.verify_password
def verify_password(account, password):
    # print("%s,%s"%(account,password))
    token = request.headers.get('X-Token')
    # print(token)
    if token == '':
        return False
    user = User.verify_auth_token(token)
    return session['username'] == user.id

# 基本路由部分：


@app.route('/')
def login():
    return render_template('index.html')


@app.route('/home')
@login_required
def home():
    return render_template('home.html')
    # return "%d" %(session['username'])


# restful api部分：
parser = reqparse.RequestParser()
parser.add_argument('username')
parser.add_argument('password')


class Login(Resource):

    def get(self):
        return {'success': 0}

    def post(self):
        args = parser.parse_args()
        user = User.query.filter_by(username=args['username']).first()
        if user is not None and user.verify_password(args['password']):
            login_user(user)
            session['username'] = user.id
            return {'success': 1}
        else:
            return {'success': 0}


class Logout(Resource):
    @auth.login_required
    def post(self):
        logout_user()
        return {'code': 20000, 'data': 'success'}


class Token(Resource):
    @login_required
    def get(self):
        token = User.query.filter_by(id=session['username']).first(
        ).generate_auth_token(expiration=5400)
        return {'code': 20000, 'data': {'token': token}}


class Roleget(Resource):
    @auth.login_required
    def get(self):
        role = User.query.filter_by(id=session['username']).first().role
        if not role:
            return {'code': 60204, 'message': '非法用户，无法获取角色'}
        else:
            data = {}
            data['roles'] = [role.name]
            data['introduction'] = role.introduction
            data['avatar'] = 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif'
            data['name'] = [role.name]
            return {'code': 20000, 'data': data}


api.add_resource(Login, '/login', endpoint='loginapi')
api.add_resource(Logout, '/prod-api/user/logout', endpoint='logoutapi')
api.add_resource(Token, '/prod-api/user/get_token', endpoint='tokenapi')
api.add_resource(Roleget, '/prod-api/user/info', endpoint='rolegetapi')
app.register_blueprint(api_bp)

if __name__ == '__main__':
    app.run(debug=True)
